package com.example.demo.controller;

import cn.hutool.json.JSONUtil;
import com.example.demo.config.NettyClientSington;
import com.example.demo.config.ZuWangWebSocket;
import com.example.demo.mapper.DataMonitorMapper;
import com.example.demo.mapper.DeviceMapper;
import com.example.demo.mapper.ExcelMapper;
import com.example.demo.pojo.PageDto;
import com.example.demo.pojo.PageResult;
import com.example.demo.pojo.RestResponse;
import com.example.demo.pojo.excel.Excel;
import com.example.demo.pojo.zuwang.SendCommandReq;
import com.example.demo.pojo.zuwang.autocheck.AutoRepairReq;
import com.example.demo.pojo.zuwang.autocheck.ZuWangAutoCheckFromJSRes;
import com.example.demo.pojo.zuwang.datamonitor.DataMonitorShowBean;
import com.example.demo.pojo.zuwang.datamonitor.DataMonitorStateBean;
import com.example.demo.pojo.zuwang.update.ZuWangUpdateReq;
import com.example.demo.pojo.zuwang.update.ZuWangUpdateToJSReq;
import com.example.demo.pojo.zuwang.zuwang.Device;
import com.example.demo.pojo.zuwang.zuwang.ZuWangReq;
import com.example.demo.util.CheckDeviceState;
import com.example.demo.util.DeviceNoConnect;
import com.example.demo.util.DeviceStateEnum;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/zuwang")
@CrossOrigin
public class ZuWangController {

    @Autowired
    private ZuWangWebSocket webSocket;

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private ExcelMapper excelMapper;

    @PostMapping("/read")
    public RestResponse read(@RequestBody PageDto bean) throws Exception {
        //根据param去获取数据库
        List<Device> resultBeans = deviceMapper.select();

        //赋值deviceName
//        for (Device resultBean : resultBeans) {
//            resultBean.setDeviceName(resultBean.getDevice().equals("YIRC") ? "远程控制装置" : "接收机");
//        }

        //过滤查询条件
        if (!StringUtils.isEmpty(bean.getDevice())) {
            resultBeans = resultBeans.stream().filter(p -> p.getDevice().contains(bean.getDevice())).collect(Collectors.toList());
        }

        //判断是否在excel
        for (Device device : resultBeans) {
            Excel seExcel = new Excel();
            seExcel.setDevice(device.getDevice());
//            seExcel.setIp(device.getIp());
            seExcel.setSn(device.getSn());
            Excel excelByUni = excelMapper.selectExcelByUni(seExcel);
            //device+sn匹配
            if (excelByUni != null) {
                if (!excelByUni.getIp().equals(device.getIp())) {
                    if (device.getState().equals(DeviceStateEnum.NORMAL.getState())) {
                        device.setState(DeviceStateEnum.UN_NORMAL.getType());//未组网
                    }
                }
            } else {
                device.setState(DeviceStateEnum.NO_DEVICE.getType());
            }

        }


        PageResult pageResult = new PageResult();
        int total = resultBeans.size();
        int page = bean.getPage() - 1;
        if (resultBeans.isEmpty()) {
            return RestResponse.success(pageResult);
        }
        List<Device> paramBeans = resultBeans.subList(bean.getLimit() * page, Math.min(resultBeans.size(), bean.getLimit() * bean.getPage()));

        //和excel比较
        pageResult.setCurrentPage(bean.getPage());
        pageResult.setTotal(total);
        pageResult.setLimit(bean.getLimit());
        pageResult.setData(paramBeans);
        return RestResponse.success(pageResult);

    }

    @PostMapping("/save")
    public RestResponse save(@RequestBody ZuWangReq zuWangReq) {

        Device device = new Device();
        BeanUtils.copyProperties(zuWangReq, device);
        device.setId(String.valueOf(UUID.randomUUID()));
        //赋值deviceName
        CheckDeviceState.setDeviceName(zuWangReq.getDevice(), device);
        device.setState(DeviceStateEnum.UN_ZUWANG.getType());//第一次保存先未组网

        device.setUni(device.getUni());
        device.setUniIp(device.getUniIp());
        deviceMapper.insert(device);

        return RestResponse.success(zuWangReq);
    }

    /**
     * {"device":"GTCZ1","target":"YSRP"
     * ,"address":{"ip":"192.168.8.233","mask":"255.255.255.0","gateway":"192.168.8.1","dns":"8.8.8.8"},"transtype":"1001"}
     *
     * @param zwUpdateReq
     * @return
     * @throws InterruptedException
     */

    @PostMapping("/update")
    public RestResponse update(@RequestBody ZuWangUpdateReq zwUpdateReq) throws InterruptedException {

        RestResponse<T> tRestResponse = DeviceNoConnect.noConnectZuwang(deviceMapper, zwUpdateReq.getDevice());
        if (!tRestResponse.isSuccessful()) {
            return tRestResponse;
        }
        sendZuwangReq(zwUpdateReq);

        return RestResponse.success();
    }

    private static void sendZuwangReq(ZuWangUpdateReq zwUpdateReq) throws InterruptedException {
        //需要对数据进行包装 --> ZuWangBeanUpdateToJS
        ZuWangUpdateToJSReq zuWangUpdateToJSReq = new ZuWangUpdateToJSReq();
        zuWangUpdateToJSReq.setDevice("YIHP");
        zuWangUpdateToJSReq.setTranstype("1001");
        zuWangUpdateToJSReq.setTarget(zwUpdateReq.getDevice());
        ZuWangUpdateToJSReq.Address address = new ZuWangUpdateToJSReq.Address();
        //暂时写死
        address.setIp(zwUpdateReq.getIp());
        address.setMask("255.255.255.0");
        address.setGateway("192.168.8.1");
        address.setDns("8.8.8.8");
        zuWangUpdateToJSReq.setAddress(address);

//        if (device.getIp().equals(zwUpdateReq.getIp())){
//            return RestResponse.validfail("ip未变更");
//        }else{
        String message = JSONUtil.toJsonStr(zuWangUpdateToJSReq);
        NettyClientSington.getNettyClient().sendMessage(message, "ZUWANG");
    }

    @PostMapping("/deletDevice")
    public RestResponse deletDevice(@RequestBody ZuWangUpdateReq zwUpdateReq) throws InterruptedException {

        deviceMapper.deleteById(zwUpdateReq.getId());
        return RestResponse.success();
    }

//    @PostMapping("/updateDeviceSuc")
//    public RestResponse updateDeviceSuc(ZuWangUpdateReq zwUpdateReq) {
//        Device device = deviceMapper.selectByUni(zwUpdateReq.getDevice() + zwUpdateReq.getSn());
//        if (device == null){
//            return RestResponse.validfail("无此设备");
//        }
//        device.setState("2");
//        deviceMapper.updateState(device);
//        return RestResponse.success();
//    }


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private DataMonitorMapper dataMonitorMapper;

    @Autowired
    ConfigFileUtil configFileUtil;


    @PostMapping("/readDataMonitorState")
    public RestResponse readDataMonitorState(@RequestBody PageDto bean) throws Exception {

        //查出全部
        List<String> uniStrs = dataMonitorMapper.selectUnis();
        List<String> nearly5Hours = dataMonitorMapper.selectNearly5Hours();

        //取出最新的时间往后5个小时
        List<DataMonitorShowBean> lists = new ArrayList<>();
        for (String uni : uniStrs) {

            DataMonitorShowBean showBean = getDataMonitorShowBean(uni, nearly5Hours);
            lists.add(showBean);
        }

        PageResult pageResult = new PageResult<DataMonitorShowBean>();
        int total = lists.size();
        int page = bean.getPage() - 1;
        if (lists.size() == 0) {
            return RestResponse.success(pageResult);
        }
        List<DataMonitorShowBean> paramBeans = lists.subList((bean.getPage() - 1) * page, Math.min(lists.size(), bean.getLimit() * bean.getPage()));

        pageResult.setCurrentPage(bean.getPage());
        pageResult.setTotal(total);
        pageResult.setLimit(bean.getLimit());
        pageResult.setData(paramBeans);
        return RestResponse.success(lists);

    }

    private DataMonitorShowBean getDataMonitorShowBean(String uni, List<String> nearly5Hours) {
        List<DataMonitorStateBean> firstBeans = dataMonitorMapper.selectById(uni);

        for (DataMonitorStateBean dm : firstBeans) {
            if (dm.getHour() != null) {
                dm.setHourStr(dm.getHour() < 10 ? "0" + dm.getHour() : "" + dm.getHour());
            }
        }

        //日期 小时 分钟 【0-9】【10-19】【20-29】【30-39】【40-49】【50-59】
        //给这1个小时拼出60个点 0异常 1正常 2没到

        //【{日期 + 小时：15个}，【日期+小时】：60个】
        Map<String, List<DataMonitorStateBean>> listMap = firstBeans.stream().collect(Collectors.groupingBy(p -> p.getDay() + " " + p.getHourStr()));

        Map<String, List<DataMonitorStateBean>> wraplistMap = new HashMap<>();
        for (String nearly5Hour : nearly5Hours) {
            wraplistMap.put(nearly5Hour, listMap.get(nearly5Hour) != null ? listMap.get(nearly5Hour) : new ArrayList<>());
        }

        //对list map的key 排序
        // 使用TreeMap并提供一个Comparator用于排序key
        Map<String, List<DataMonitorStateBean>> sortedMap = new TreeMap<>(new Comparator<String>() {
            @Override
            public int compare(String k1, String k2) {
                // 对于字符串key升序排序
                return k2.compareTo(k1);
                // 若需要降序排序，则可以改为
                // return k2.compareTo(k1);
            }
        });
        sortedMap.putAll(wraplistMap);

        DataMonitorShowBean showBean = new DataMonitorShowBean();
        showBean.setDevice(firstBeans.get(0).getDevice());
        showBean.setIp(firstBeans.get(0).getIp());
        showBean.setSn(firstBeans.get(0).getSn());


        for (Map.Entry<String, List<DataMonitorStateBean>> entry : sortedMap.entrySet()) {
            String key = entry.getKey();
            List<Integer> minList = entry.getValue().stream().map(DataMonitorStateBean::getMinute).collect(Collectors.toList());
            //生成一个全部 0的字符串
            StringBuffer onlineStatistics = new StringBuffer();
            for (int i = 0; i < 60; i++) {
                if (minList.contains(i)) {
                    onlineStatistics.append("1");
                } else if (minList.isEmpty() || i > minList.get(0)) {
                    onlineStatistics.append("2");
                } else {
                    onlineStatistics.append("0");
                }
            }

            DataMonitorShowBean.HourInfo info = new DataMonitorShowBean.HourInfo();
            info.setHour(key);
            info.setStateBeans(entry.getValue());
            info.setOnlineStatistics(onlineStatistics.toString());
            List<String> states = new ArrayList<>();
            int jinge = 10;
            for (int i = 0; i < 6; i++) {
                states.add(onlineStatistics.toString().substring(i * jinge, (i + 1) * jinge));
            }
            info.setStates(states);

            showBean.getHourInfoList().add(info);

        }
        return showBean;
    }

    /**
     * 读取接收机自检测参数
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/loadAutoCheck_jieshou")
    public RestResponse loadAutoCheck_jieshou() throws Exception {

        //从本地文件里读取自检测参数
        List<ZuWangAutoCheckFromJSRes> zuWangAutoCheckFromJSRess = configFileUtil.readAutoCheck_jieshou();
        return RestResponse.success(zuWangAutoCheckFromJSRess.get(0));
    }

    /**
     * 读取远程自检测参数
     *
     * @return
     * @throws Exception
     */
    @PostMapping("/loadAutoCheck_remote")
    public RestResponse loadAutoCheck_remote() throws Exception {

        //从本地文件里读取自检测参数
        List<ZuWangAutoCheckFromJSRes> zuWangAutoCheckFromJSRess = configFileUtil.readAutoCheck_remoteControl();
        return RestResponse.success(zuWangAutoCheckFromJSRess.get(0));
    }


    @PostMapping("/autoCheck")
    public RestResponse autoCheck(@RequestBody SendCommandReq req) throws Exception {

//        if (DemoUdpNettyServerHandler.senderMap.get(req.getTarget()) == null) {
//            Device device = deviceMapper.selectByTarget(req.getTarget());
//            device.setState("0");
//            deviceMapper.updateState(device);
//            return RestResponse.validfail( device.getDeviceName() + "连接没有建立，请稍后再试");
//        }
        RestResponse<T> tRestResponse = DeviceNoConnect.noConnect(deviceMapper, req.getTarget());
        if (!tRestResponse.isSuccessful()) {
            return tRestResponse;
        }


        NettyClientSington.getNettyClient().sendMessage(JSONUtil.toJsonStr(req), req.getTarget());
        return RestResponse.success();
    }


    @PostMapping("/autoRepair")
    public RestResponse autoRepair(@RequestBody AutoRepairReq req) throws Exception {

        RestResponse<T> tRestResponse = DeviceNoConnect.noConnect(deviceMapper, req.getTarget());
        if (!tRestResponse.isSuccessful()) {
            return tRestResponse;
        }

        NettyClientSington.getNettyClient().sendMessage(JSONUtil.toJsonStr(req), req.getTarget());
        return RestResponse.success();
    }


}
